package com.peza.bikelog.common.util;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.QName;

import com.peza.bikelog.common.domain.garmin.ObjectFactory;


public class XmlConverterImpl implements XmlConverter{

	private JAXBContext jaxbContext;
	
	public static final String XML_ROOT_ELEMENT = "TrainingCenterDatabase";
	public static final String XML_SCHEMA_LOCATION = "http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2 http://www.garmin.com/xmlschemas/TrainingCenterDatabasev2.xsd";
	public static final String XML_NAMESPACE_1 = "http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2";
	
	@Override
	public <T> T createObject(String xml, Class <T> clazz){
		T obj = null;
		//1. We need to create JAXContext instance
		try {
			jaxbContext = JAXBContext.newInstance(ObjectFactory.class);
		    Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
		    
		    StringReader reader = new StringReader(xml);
		    JAXBElement<T> unmarshalledObject = (JAXBElement<T>) unmarshaller.unmarshal(reader);
		    obj = unmarshalledObject.getValue();
		    
		} catch (JAXBException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return obj;
	    
	}
	
	@Override
	public <T> T createObject(File file, Class <T> clazz){
		T obj = null;
		
		try {
			jaxbContext = JAXBContext.newInstance(ObjectFactory.class);
		    Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
		    
		    JAXBElement<T> unmarshalledObject = (JAXBElement<T>) unmarshaller.unmarshal(file);
		    obj = unmarshalledObject.getValue();
		    
		} catch (JAXBException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return obj;
	    
	}

	@Override
	public <T> byte[] createXml(T object, Class<T> clazz) {
		
		StringWriter writer = new StringWriter();

		try {
			jaxbContext = JAXBContext.newInstance(ObjectFactory.class);
		    Marshaller marshaller = jaxbContext.createMarshaller();
		    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
		    marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, XML_SCHEMA_LOCATION);
		    marshaller.marshal(new JAXBElement<T>(new QName(XML_NAMESPACE_1,XML_ROOT_ELEMENT), clazz, object), writer);
		    			
		} catch (JAXBException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		String output = writer.toString();
		
		final String REGEX = "<TrainingCenterDatabase(.*)?>"; 

		Pattern p = Pattern.compile(REGEX);
		Matcher m = p.matcher(output);
		String target = "";
		if (m.find()) {
			target = m.group(1);
			output = output.replace(target, ADDITIONAL_NS);
		}
				
		return writer.toString().getBytes();
	}

	

	private static final String ADDITIONAL_NS = "" +
			"xmlns:ns5=\"http://www.garmin.com/xmlschemas/ActivityGoals/v1\" " +
			"xmlns:ns3=\"http://www.garmin.com/xmlschemas/ActivityExtension/v2\" " +
			"xmlns:ns2=\"http://www.garmin.com/xmlschemas/UserProfile/v2\" " +
			"xmlns:ns4=\"http://www.garmin.com/xmlschemas/ProfileExtension/v1\" ";

	
}
